package com.glw.sso.platform.common.base;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.LambdaUtils;
import com.baomidou.mybatisplus.core.toolkit.support.ColumnCache;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import com.glw.sso.platform.common.group.Insert;
import com.glw.sso.platform.common.group.Update;
import com.glw.sso.platform.common.response.Response;
import io.swagger.annotations.ApiParam;
import io.swagger.v3.oas.annotations.Operation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;

import javax.validation.constraints.NotNull;
import java.io.Serializable;
import java.lang.reflect.Field;
import java.util.Map;

/**
 * @Author: guoliwei
 * @Date: 2021/10/31 19:34
 * @Version 1.0
 */
@Slf4j
public abstract class BaseController<S extends IService<T>, T> {

    protected abstract S getService();

    @Operation(summary = "list")
    @GetMapping("list")
    public Response list(T entity) throws IllegalAccessException {
        return Response.succeeded(getService().list(buildQueryWrapper(entity)));
    }

    @Operation(summary = "page")
    @GetMapping("page")
    public Response page(Page<T> page, T entity) throws IllegalAccessException {
        return Response.succeeded(getService().page(page, buildQueryWrapper(entity)));
    }

    @Operation(summary = "get")
    @GetMapping("get")
    public Response get(T entity) throws IllegalAccessException {
        return Response.succeeded(getService().getOne(buildQueryWrapper(entity)));
    }

    @Operation(summary = "get")
    @GetMapping("get/{id}")
    public Response get(@ApiParam(required = true, value = "id")
                        @NotNull(message = "id不能为空")
                        @PathVariable Serializable id) {
        return Response.succeeded(getService().getById(id));
    }

    @Operation(summary = "save")
    @PostMapping("save")
    public Response save(@RequestBody @Validated(Insert.class) T entity) {
        return getService().save(entity) ? Response.succeeded() : Response.failed("save fail");
    }

    @Operation(summary = "modify")
    @PostMapping("modify")
    public Response modify(@RequestBody @Validated(Update.class) T entity) {
        return getService().updateById(entity) ? Response.succeeded() : Response.failed("update fail");
    }

    @Operation(summary = "remove")
    @GetMapping("remove/{id}")
    public Response remove(@ApiParam(required = true, value = "id")
                           @NotNull(message = "id不能为空")
                           @PathVariable Serializable id) {
        return getService().removeById(id) ? Response.succeeded() : Response.failed("remove fail");
    }

    private QueryWrapper<T> buildQueryWrapper(T entity) throws IllegalAccessException {
        return buildQueryWrapper(entity.getClass(), entity, new QueryWrapper<>());
    }

    private QueryWrapper<T> buildQueryWrapper(Class clz, T entity, QueryWrapper<T> queryWrapper) throws IllegalAccessException {
        queryWrapper = queryWrapper == null ? new QueryWrapper<>() : queryWrapper;
        Map<String, ColumnCache> columnMap = LambdaUtils.getColumnMap(clz);
        Field[] fields = clz.getDeclaredFields();

        for (Field field : fields) {
            field.setAccessible(true);
            Object value = field.get(entity);
            // value 为空不拼接
            if (value == null) {
                continue;
            }
            // 如果是String判断是否为空字符串，为空不拼接
            if (value instanceof String && ((String) value).isEmpty()) {
                continue;
            }
            // 不存在的列不拼接
            if (!columnMap.containsKey(field.getName().toUpperCase())) {
                continue;
            }

            queryWrapper.eq(columnMap.get(field.getName().toUpperCase()).getColumn(), field.get(entity));
        }

        Class<?> superclass = clz.getSuperclass();
        if (superclass != null) {
            this.buildQueryWrapper(superclass, entity, queryWrapper);
        }
        return queryWrapper;
    }
}
